If they're value types, it means they can be copied, and copied fairly easily by the user (as simply as a = b;). Copying a GPU resource can be quite an expensive operation, so I'd see value-references as quite a dangerous API. Also, there's no point in cloning some GPU resources -- e.g. in D3D a shader program is just code (no other state), so there's no need in ever having more than one instance of a particular program hanging around.
This was my intuition of the situation, where for the most part you want shallow copies and reference semantics. If deep copies are required then that should be offered explicitly and cannot just happen 'by mistake'.
One option that hasn't been discussed is to use non-copyable values. This avoids the issue of expensive copies by out-right preventing them.
You might still use shared_ptrs to share access to these objects - but there is a big difference between "an object that moves with reference semantics" and "an object passed by reference". By still being a value it allows you to also pass them by the cheaper plain reference or raw pointer. It also allows them to be stored more efficiently in contiguous arrays.
The precise way in which access to the object is passed around is a choice for the client code, not enforced by the handle type itself.
This makes a lot of sense especially if you only have one point of control, e.g. a resource manager/resource cache, which owns the 'real' resource. Client code can then request weak/non-owning references to these resources.
This is something I'll probably be playing around with pretty soon for meshes and materials. At the moment I have each object naively loading (and owning) its own textures and meshes, which while convenient is not particularly clever.