class_docstr: A `Node` describes the connectivity between two layers.
  
  Each time a layer is connected to some new input,
  a node is added to `layer._inbound_nodes`.
  Each time the output of a layer is used by another layer,
  a node is added to `layer._outbound_nodes`.
  
  Args:
      layer: The Layer for the Layer.__call__ this node represents.
      call_args: The positional arguments the Layer was called with.
      call_kwargs: The keyword arguments the Layer was called with.
      outputs: The outputs of the Layer.__call__
class_docstr_tok: ["A","`","Node","`","describes","the","connectivity","between","two","layers",".","Each","time","a","layer","is","connected","to","some","new","input",",","a","node","is","added","to","`","layer._inbound_nodes","`",".","Each","time","the","output","of","a","layer","is","used","by","another","layer",",","a","node","is","added","to","`","layer._outbound_nodes","`",".","Args",":","layer",":","The","Layer","for","the","Layer.__call__","this","node","represents",".","call_args",":","The","positional","arguments","the","Layer","was","called","with",".","call_kwargs",":","The","keyword","arguments","the","Layer","was","called","with",".","outputs",":","The","outputs","of","the","Layer.__call__"]
code: def __init__(
      self, layer, call_args=None, call_kwargs=None, outputs=None
  ):
      call_args = [] if call_args is None else call_args
      call_kwargs = {} if call_kwargs is None else call_kwargs
      outputs = [] if outputs is None else outputs
  
      self.layer = layer
      self.is_input = not call_args and not call_kwargs
  
      # These arguments are user-provided. Copy the structures here so that
      # future user modifications do not affect the node's metadata.
      # We copy using map_structure rather than python's shallow or deep copy,
      # because the args can be data structures (so shallow copy is
      # insufficient), but individual values might not support copy.copy
      # or be too expensive to deep copy.
      call_args = nest.map_structure(lambda t: t, call_args)
      call_kwargs = nest.map_structure(lambda t: t, call_kwargs)
      self.outputs = nest.map_structure(lambda t: t, outputs)
      self.call_args = call_args
      self.call_kwargs = call_kwargs
  
      # Cached for performance.
      self._flat_arguments = nest.flatten(
          (self.call_args, self.call_kwargs)
      )
      # Used to avoid expensive `nest` operations in the most common case.
      self._single_positional_tensor_passed = (
          not self.call_kwargs
          and len(self.call_args) == 1
          and tensor_util.is_tf_type(self.call_args[0])
      )
  
      if not ops.executing_eagerly_outside_functions():
          # Create TensorFlowOpLayers if needed (in TF1)
          for obj in self._flat_arguments:
              if isinstance(
                  obj, tensor_lib.Tensor
              ) and base_layer_utils.needs_keras_history(
                  obj, ignore_call_context=True
              ):
                  base_layer_utils.create_keras_history(obj)
  
      self._keras_inputs = []
      self._keras_inputs_ids_and_indices = []
      for i, ele in enumerate(self._flat_arguments):
          if is_keras_tensor(ele):
              self._keras_inputs.append(ele)
              kt_id = str(id(ele))
              kt_index = i
              self._keras_inputs_ids_and_indices.append(
                  (kt_id, kt_index)
              )
  
      # Wire up Node to Layers.
      self.layer._inbound_nodes.append(self)
      for kt in self.keras_inputs:
          inbound_layer = kt._keras_history.layer
          if inbound_layer is not None:  # `None` for `Input` tensors.
              inbound_layer._outbound_nodes.append(self)
  
      # Set metadata on outputs.
      node_index = len(self.layer._inbound_nodes) - 1
      for i, tensor in enumerate(nest.flatten(outputs)):
          tensor._keras_history = KerasHistory(
              layer=layer, node_index=node_index, tensor_index=i
          )
  
      # Cached for performance.
      self.flat_input_ids = [str(id(t)) for t in self._keras_inputs]
      self.flat_output_ids = [
          str(id(t)) for t in nest.flatten(self.outputs)
      ]
  
imports: import collections
  import copy
  import json
  import numpy
  from tensorflow.python.framework import ops
  from tensorflow.python.framework import tensor
  from tensorflow.python.framework import tensor_util
  from tensorflow.python.keras import backend
  from tensorflow.python.keras.engine import base_layer_utils
  from tensorflow.python.keras.saving.saved_model import json_utils
  from tensorflow.python.keras.utils import tf_utils
  from tensorflow.python.util import nest
label_desc: Use image node_id 1 to create a new Node object  with example: obj = Node(layer, call_args, call_kwargs, outputs)