def subgraph_grad(wrt, end, start=None, cost=None, details=False):
    assert ((cost is not None) or (start is not None))
    assert isinstance(end, list)
    assert isinstance(wrt, list)
    if start is not None:
        assert isinstance(start, dict)

    params = list(set(wrt + end))

    start_grads = None
    cost_grads = None
    if start is not None:
        start_grads = list(
            theano.grad(
                cost=None, wrt=params, known_grads=start,
                consider_constant=end,
                disconnected_inputs='ignore'
            )
        )

    if cost is not None:
        cost_grads = list(
            theano.grad(
                cost=cost, wrt=params,
                consider_constant=end,
                disconnected_inputs='ignore'
            )
        )

    grads = None
    if start is None:
        grads = cost_grads
    else:
        grads = start_grads
        if cost_grads is not None:
            for i in range(len(grads)):
                grads[i] += cost_grads[i]

    pgrads = OrderedDict(izip(params, grads))
    # separate wrt from end grads:
    wrt_grads = list(pgrads[k] for k in wrt)
    end_grads = list(pgrads[k] for k in end)

    if details:
        return wrt_grads, end_grads, start_grads, cost_grads

    return wrt_grads, end_grads
With respect to `wrt`, computes gradients of cost and/or from
dataset/ETHPy150Open rizar/attention-lvcsr/libs/Theano/theano/gradient.py/subgraph_grad