def decode_lazy(rlp, sedes=None, **sedes_kwargs):
    """Decode an RLP encoded object in a lazy fashion.

    If the encoded object is a bytestring, this function acts similar to
    :func:`rlp.decode`. If it is a list however, a :class:`LazyList` is
    returned instead. This object will decode the string lazily, avoiding
    both horizontal and vertical traversing as much as possible.

    The way `sedes` is applied depends on the decoded object: If it is a string
    `sedes` deserializes it as a whole; if it is a list, each element is
    deserialized individually. In both cases, `sedes_kwargs` are passed on.
    Note that, if a deserializer is used, only "horizontal" but not
    "vertical lazyness" can be preserved.

    :param rlp: the RLP string to decode
    :param sedes: an object implementing a method ``deserialize(code)`` which
                  is used as described above, or ``None`` if no
                  deserialization should be performed
    :param \*\*sedes_kwargs: additional keyword arguments that will be passed
                             to the deserializers
    :returns: either the already decoded and deserialized object (if encoded as
              a string) or an instance of :class:`rlp.LazyList`
    """
    item, end = consume_item_lazy(rlp, 0)
    if end != len(rlp):
        raise DecodingError('RLP length prefix announced wrong length', rlp)
    if isinstance(item, LazyList):
        item.sedes = sedes
        item.sedes_kwargs = sedes_kwargs
        return item
    elif sedes:
        return sedes.deserialize(item, **sedes_kwargs)
    else:
        return item