import torch


def unbatch(d, ignore=[]):
    """
    Convert a dict of batched tensors to a list of tensors per entry. Ignore any
    keys in the list.
    """
    ignore = set(ignore)

    to_unbatch = {}
    for k, v in d.items():
        # Skip ignored keys.
        if k in ignore:
            continue
        if isinstance(v, torch.Tensor):
            # Detach and convert tensors to CPU.
            new_v = v.detach().cpu().numpy()
        else:
            new_v = v

        to_unbatch[k] = new_v

    # Make sure all entries have same length.
    lengths = [len(v) for v in to_unbatch.values()]
    if len(set(lengths)) != 1:
        raise ValueError("All values must be of same length.")

    res = []
    for i in range(lengths[0]):
        to_append = {}
        for k, v in to_unbatch.items():
            to_append[k] = v[i]

        res.append(to_append)

    return res