docstr: Private utility to retrieves an attribute (e.g. inputs) from a node.
  
  This is used to implement the properties:
  - output
  - input
  
  Args:
      node_index: Integer index of the node from which
          to retrieve the attribute.
      attr: Exact node attribute name.
      attr_name: Human-readable attribute name, for error messages.
  
  Returns:
      The operation's attribute `attr` at the node of index `node_index`.
docstr_tok: ["Private","utility","to","retrieves","an","attribute","(","e.g",".","inputs",")","from","a","node",".","This","is","used","to","implement","the","properties",":","-","output","-","input","Args",":","node_index",":","Integer","index","of","the","node","from","which","to","retrieve","the","attribute",".","attr",":","Exact","node","attribute","name",".","attr_name",":","Human-readable","attribute","name",",","for","error","messages",".","Returns",":","The","operation","'s","attribute","`","attr","`","at","the","node","of","index","`","node_index","`","."]
code: def _get_node_attribute_at_index(self, node_index, attr, attr_name):
      """Private utility to retrieves an attribute (e.g. inputs) from a node.
  
      This is used to implement the properties:
      - output
      - input
  
      Args:
          node_index: Integer index of the node from which
              to retrieve the attribute.
          attr: Exact node attribute name.
          attr_name: Human-readable attribute name, for error messages.
  
      Returns:
          The operation's attribute `attr` at the node of index `node_index`.
      """
      if not self._inbound_nodes:
          raise ValueError(
              f"The layer {self.name} has never been called "
              f"and thus has no defined {attr_name}."
          )
      if not len(self._inbound_nodes) > node_index:
          raise ValueError(
              f"Asked to get {attr_name} at node "
              f"{node_index}, but the operation has only "
              f"{len(self._inbound_nodes)} inbound nodes."
          )
      values = getattr(self._inbound_nodes[node_index], attr)
      if isinstance(values, list) and len(values) == 1:
          return values[0]
      else:
          return values
  
imports: import inspect
  import textwrap
  import tree
  from keras import backend
  from keras.api_export import keras_export
  from keras.backend.common.keras_tensor import any_symbolic_tensors
  from keras.ops.node import Node
  from keras.utils import python_utils
  from keras.utils import traceback_utils
  from keras.utils.naming import auto_name
label_desc: Use image node_id 12 for calling the Operation obj's underlying member method code with example usage: obj._get_node_attribute_at_index(node_index, attr, attr_name) and returns: values, values