code: def map_storage(
      fgraph, order, input_storage, output_storage, storage_map=None
  ):
      """Ensure there is storage (a length-1 list) for inputs, outputs, and interior nodes.
  
      :param fgraph: The current fgraph.  This function uses the inputs and outputs attributes.
      :param order: an iterable over Apply instances (in program running order)
      :param input_storage: None or existing input storage (see below)
      :param output_storage: None or existing output storage (see below)
  
      :rtype: 3-tuple
      :returns: (list of storage for inputs, list of storage for outputs, and the `storage_map`)
  
      Parameters
      ----------
      fgraph
          The current fgraph. This function uses the inputs and outputs
          attributes.
      order
          An iterable over Apply instances (in program running order).
      input_storage
          None or existing input storage (see below).
      output_storage
          None or existing output storage (see below).
  
      Returns
      -------
      3-tuple
          List of storage for inputs, list of storage for outputs, and
          the `storage_map`.
  
      Extended summary
      ----------------
      This function iterates over the nodes in `order` and ensures that for every
      input and output `Variable`, there is a unique storage container. This is
      returned as a dictionary Variable -> storage called the `storage_map`.
  
      This function also returns `input_storage`, which is a list of storages
      corresponding to fgraph.inputs.
      This function also returns `output_storage`, which is a list of storages
      corresponding to fgraph.outputs.
  
      """
      # each Apply argument's data is stored in a list of length 1 (these lists act like pointers)
  
      if storage_map is None:
          storage_map = {}
  
      # input_storage is a list of data-containers for the inputs.
      if input_storage is None:
          input_storage = [[None] for input in fgraph.inputs]
      else:
          assert len(fgraph.inputs) == len(input_storage)
  
      # add input storage into storage_map
      for r, storage in zip(fgraph.inputs, input_storage):
          if r in storage_map:
              assert storage_map[r] is storage, (
                  "Given input_storage conflicts "
                  "with storage in given storage_"
                  "map. Given input_storage: ",
                  storage,
                  "Storage in storage_ma" "p: ",
                  storage_map[r],
              )
          else:
              storage_map[r] = storage
      #     for orphan in fgraph.orphans:
      #         if not isinstance(orphan, Constant):
      #             raise TypeError("Cannot link a graph with non-constant orphans.", orphan)
      #         storage_map[orphan] = [orphan.data]
  
      # allocate output storage
      if output_storage is not None:
          assert len(fgraph.outputs) == len(output_storage)
          for r, storage in zip(fgraph.outputs, output_storage):
              if r in storage_map:
                  assert storage_map[r] is storage, (
                      "Given output_storage confl"
                      "icts with storage in given"
                      " storage_map. Given output"
                      "_storage: ",
                      storage,
                      "Sto" "rage in storage_map: ",
                      storage_map[r],
                  )
              else:
                  storage_map[r] = storage
  
      # allocate storage for intermediate computation
      for node in order:
          for r in node.inputs:
              if r not in storage_map:
                  assert isinstance(r, graph.Constant)
                  storage_map[r] = [r.data]
          for r in node.outputs:
              storage_map.setdefault(r, [None])
      for r in fgraph.outputs:
          if isinstance(r, graph.Constant):
              storage_map.setdefault(r, [r.data])
  
      # extract output storage
      if output_storage is None:
          output_storage = [storage_map[r] for r in fgraph.outputs]
  
      return input_storage, output_storage, storage_map
  
imports: from __future__ import absolute_import, print_function, division
  from copy import copy, deepcopy
  from sys import getsizeof
  import sys
  import traceback
  import numpy
  import theano
  from theano.compat import izip
  from six import reraise
  from six.moves import StringIO
  from theano.gof import utils
  from theano.gof import graph
  from theano.gof.type import Type
  from .utils import undef
label_desc: Use image node_id 4 for calling a global function with example usage: map_storage(fgraph, order, input_storage, output_storage, storage_map) and returns: input_storage,  output_storage,  storage_map