I decided this time that since I only ever have one graphics device, there is no real point in having a GraphicsDevice class other than a similar warm fuzzy singleton-esque feeling, so instead the device is just wrapped by functions in a namespace.
I've also been looking into DrawPrimitiveUP over proper vertex buffers. According to this, it would appear that for relatively small batches of vertices, there is no significant advantage of using a vertex buffer over DrawPrimitiveUP() with a std::vector.
There are clear advantages to just using a std::vector - no more worrying about maximum buffer sizes (within reason), one less class wrapper to write and one less Direct3D resource for either me or Direct3D to manage in the event of device loss.
I note there is also a DrawIndexedPrimitiveUP(), although I'm doubtful that for batches of the kind of size that a mainly textured quad based project will use would reap any significant benefit from using this. Nice to have it in mind for a potential future optimisation if the need arises.
As I suspected when I started on Direc3D a year or so ago, rewritting the Direct3D wrapping code each time I've started a new project has gradually made me more and more comfortable with Direct3D directly, without me really noticing me learning.
The original point of learning Direct3D for 2D games was to get comfortable enough with the basic principles to make the move to 3D more feasible - I think I'm pretty much there now, so hopefully after this current project is either finished or dies, I can start to think seriously about a 3D game.