'Computes output tensors for new inputs.
# Note:
- Expects `inputs` to be a list (potentially with 1 element).
- Can be run on non-Keras tensors.
# Arguments
inputs: List of tensors
masks: List of masks (tensors or None).
# Returns
Three lists: output_tensors, output_masks, output_shapes'

def run_internal_graph(self, inputs, masks=None):

    if (masks is None):
        masks = [None for _ in range(len(inputs))]
    tensor_map = {}
    for (x, y, mask) in zip(self.inputs, inputs, masks):
        tensor_map[str(id(x))] = (y, mask)
    depth_keys = list(self.nodes_by_depth.keys())
    depth_keys.sort(reverse=True)
    for depth in depth_keys:
        nodes = self.nodes_by_depth[depth]
        for node in nodes:
            layer = node.outbound_layer
            reference_input_tensors = node.input_tensors
            reference_output_tensors = node.output_tensors
            computed_data = []
            for x in reference_input_tensors:
                if (str(id(x)) in tensor_map):
                    computed_data.append(tensor_map[str(id(x))])
            if (len(computed_data) == len(reference_input_tensors)):
                with K.name_scope(layer.name):
                    if node.arguments:
                        kwargs = node.arguments
                    else:
                        kwargs = {}
                    if (len(computed_data) == 1):
                        (computed_tensor, computed_mask) = computed_data[0]
                        if has_arg(layer.call, 'mask'):
                            if ('mask' not in kwargs):
                                kwargs['mask'] = computed_mask
                        output_tensors = _to_list(layer.call(computed_tensor, **kwargs))
                        output_masks = _to_list(layer.compute_mask(computed_tensor, computed_mask))
                        computed_tensors = [computed_tensor]
                        computed_masks = [computed_mask]
                    else:
                        computed_tensors = [x[0] for x in computed_data]
                        computed_masks = [x[1] for x in computed_data]
                        if has_arg(layer.call, 'mask'):
                            if ('mask' not in kwargs):
                                kwargs['mask'] = computed_masks
                        output_tensors = _to_list(layer.call(computed_tensors, **kwargs))
                        output_masks = _to_list(layer.compute_mask(computed_tensors, computed_masks))
                    if (hasattr(layer, 'activity_regularizer') and (layer.activity_regularizer is not None)):
                        regularization_losses = [layer.activity_regularizer(x) for x in computed_tensors]
                        layer.add_loss(regularization_losses, computed_tensors)
                self.add_update(layer.get_updates_for(computed_tensors), inputs)
                self.add_update(layer.get_updates_for(None), None)
                self.add_loss(layer.get_losses_for(computed_tensors), inputs)
                self.add_loss(layer.get_losses_for(None), None)
                if all([hasattr(x, '_keras_shape') for x in computed_tensors]):
                    if (len(computed_tensors) == 1):
                        shapes = _to_list(layer.compute_output_shape(computed_tensors[0]._keras_shape))
                        uses_learning_phase = computed_tensors[0]._uses_learning_phase
                    else:
                        shapes = _to_list(layer.compute_output_shape([x._keras_shape for x in computed_tensors]))
                        uses_learning_phase = any([x._uses_learning_phase for x in computed_tensors])
                    for (x, s) in zip(output_tensors, shapes):
                        x._keras_shape = s
                        x._uses_learning_phase = (getattr(x, '_uses_learning_phase', False) or uses_learning_phase)
                for (x, y, mask) in zip(reference_output_tensors, output_tensors, output_masks):
                    tensor_map[str(id(x))] = (y, mask)
    output_tensors = []
    output_masks = []
    output_shapes = []
    for x in self.outputs:
        assert (str(id(x)) in tensor_map), ('Could    not    compute    output    ' + str(x))
        (tensor, mask) = tensor_map[str(id(x))]
        if (hasattr(tensor, '_keras_shape') and (output_shapes is not None)):
            shape = tensor._keras_shape
            output_shapes.append(shape)
        else:
            output_shapes = None
        output_tensors.append(tensor)
        output_masks.append(mask)
    cache_key = ','.join([str(id(x)) for x in inputs])
    cache_key += ('_' + ','.join([str(id(x)) for x in masks]))
    if (len(output_tensors) == 1):
        output_tensors = output_tensors[0]
        self._output_tensor_cache[cache_key] = output_tensors
    else:
        self._output_tensor_cache[cache_key] = output_tensors
    if (len(output_masks) == 1):
        output_masks = output_masks[0]
        self._output_mask_cache[cache_key] = output_masks
    else:
        self._output_mask_cache[cache_key] = output_masks
    if (output_shapes is not None):
        input_shapes = [x._keras_shape for x in inputs]
        cache_key = ','.join([str(x) for x in input_shapes])
        if (len(output_shapes) == 1):
            output_shapes = output_shapes[0]
            self._output_shape_cache[cache_key] = output_shapes
        else:
            self._output_shape_cache[cache_key] = output_shapes
    return (output_tensors, output_masks, output_shapes)
