I've found a mechanism that uses the "interleaved attribs" feature of transform feedbacks to spit out 4 verts at a time (as six to draw two GL_TRIANGLES) into a buffer that a quad-drawing shader program consumes.
Using GL_POINTS/gl_PointCoord is probably better though just for teaching children fundamentals, I just wish that it actually worked properly in practice.
Furthermore, depending on the GPU and the exact workload, it can be that vertex and fragment shading can run in parallel. In that case, it is better to spread the load over both, instead of letting the fragment shaders do everything.
The same goes for texturing. Instead of calculating most of the ball's color pattern in the fragment shader, and only using texture lookups for the number itself, if you just have a texture covering the whole ball, you basically offload a lot of computation to the texture units.
That said, for a pool game where the balls are one of the most important items on the screen, it's probably worth it to get the perfect smoothness and lighting, as you mentioned.