It really depends what you want to, the example I linked it was just to show the use of uniforms
if you do not want to generate new vertex buffers and optimise the draw process then you will have to make your own circle_2d assuming you want to draw circles. If you want to move things around then you can have a face that is moved via translation on the uniforms.
Of course if you aim for a large collection of primitives , you should not be using this approach anyway because as I said python will become the bottleneck here.
What I would have done , have one face, one vertex buffer, one index buffer and one texture and then use Cairo to draw the actual primitives and then just use the texture that Cairo would create (basically a simple image) with the GPU module on top of the face.
Cairo is coded in C so you will be getting far higher performance per draw call. Cairo is by far the most popular vector graphics library out there with many popular users, one of them being Firefox.
Of course if you want to do 3d primitives, then Cairo cannot help you there.
Concering GPUVertexBuf , you are correct there is no way to edit them directly. Which is why circle_2d generates new ones each time.