def lazy_property(func):
    """Decorator that makes a property lazy-evaluated"""
    attr_name = "_lazy_" + func.__name__

    @property
    def _lazy_property(self):
        """Function for property lazy-evaluate decorator"""
        if not hasattr(self, attr_name):
            # The attr doesn't exist yet, so call the function (`func`) that has
            # the decorator. The result of that call is set in the attr.
            #
            # It's okay to set (read: memoise) the client as an attr since we
            # each call to the client's functions (e.g. `list`) are not
            # memoised.
            setattr(self, attr_name, func(self))

        # Get the result of the function call that was set in the attr.
        return getattr(self, attr_name)

    return _lazy_property