Make cached_property more flexible

This allows models to have a cached property as well as a "fresh" accessor.

    class Foo(object):

        def get_bar(self):
            .... heavy work here ....

        bar = cached_property(get_bar, name='bar')

We can't do this with the existing cached_property because it stuffs its cached value into the objects __dict__ using the name of the function, which would mask the function itself.