Why is the graph for the 'TFOpLambda' layer's 'call' method not stored in the SavedModel object_graph_def? 
@meghendra Pls check whether the solution works for you or not.

Regarding your first question, as far as I know, there is no way to force the serialization of the 'call' method graph for TFOpLambda layers in newer versions of TensorFlow. This change in serialization was made intentionally, and it is not recommended to rely on internal details of the SavedModel format in order to recreate a model in another framework.

Regarding your second question, the main benefit of using TFOpLambda layers over TensorFlowOpLayers is that they are more general and flexible. TFOpLambda layers allow you to use any TensorFlow operation (not just those provided by tf.keras.layers) as a layer in your model. This can be useful for example when you want to use a custom TensorFlow operation that is not available as a pre-built layer in tf.keras. TFOpLambda layers also allow you to easily wrap a TensorFlow function (or any Python function) as a layer. This can be useful when you want to use a complex computation that cannot be expressed as a single TensorFlow operation, but you still want to treat it as a layer in your model.

One possible solution would be to manually reconstruct the 'call' method graph for TFOpLambda layers based on their metadata. In the example you provided, the metadata contains information about the function used ('nn.relu') and its inbound nodes (in this case, the previous layer 'conv1d_13').  @NiharJani2002 thank you so much for your quick answer!
To an extent, I am already using the solution you suggested. What I am doing right now is to map these well-known activation function names, viz. nn.relu, math.tanh to implementations in MATLAB and using the inbound nodes for the function arguments. 

But for arbitrary TensorFlow or Python functions wrapped in TFOpLambda layers, this won't be the case. Hence my follow up question is:
   While the metadata for the TFOpLambda layer in this example specifies the name of the function being used (say, nn.relu), is the graph for this function serialized somewhere in the SavedModel?  @meghendra
In general, the graph for a function wrapped in a TFOpLambda layer is not serialized in the SavedModel format. When you define a TFOpLambda layer using a TensorFlow or Python function, what gets saved in the SavedModel is the name of the function, as well as any arguments that were passed to the function at the time the layer was created.

When the SavedModel is loaded and the TFOpLambda layer is instantiated, the function is reconstructed using the name and arguments that were saved. However, the actual graph for the function is not included in the SavedModel, and must be available at runtime in order for the layer to work.

For well-known activation functions like nn.relu or math.tanh, the implementation of the function is typically available in most frameworks, including MATLAB. This allows you to map the function name to the implementation and use it in your MATLAB code.

However, for arbitrary TensorFlow or Python functions wrapped in TFOpLambda layers, the implementation may not be available in other frameworks. In this case, you would need to manually.
 @NiharJani2002 thanks for the clarification.
### Describe the problem

I work on importing TensorFlow models into MATLAB, this includes de-serializing the SavedModel format, identifying the different tf.keras.layers present in the SavedModel and creating an equivalent deep learning network in MATLAB. 

In TensorFlow 2.3.0 and earlier , if we use a TF symbol (like: tf.nn.relu()) between tf.keras.layers instances, it was serialized as a 'TensorFlowOpLayer', that was similar to a layer subclassing tf.keras.layer, i.e., the graph for its 'call' method (call_and_return_conditional_losses) was stored in the SavedModel. Specifically, this 'call_and_return_conditional_losses' function was stored as a child of the node corresponding to the TensorFlowOpLayer in the SavedModel's object_graph_def. 

In TensorFlow 2.6.0 and later, a TF symbol used between tf.keras.layers instances is serialized as a 'TFOpLambda' layer. Saving models containing these TFOpLambda layers into a SavedModel does not serialize the graph for its 'call' method (call_and_return_conditional_losses) anymore. There is no child node of the TFOpLambda node in the SavedModel's object_graph_def that corresponds to the 'call_and_return_conditional_losses' function anymore. 

This creates a problem for me since I rely on decoding the 'call_and_return_conditional_losses' function, in order to import these TensorFlowOpLayer / TFOpLambda into MATLAB. Consider the following model as an example:

```
x = tf.keras.layers.Input(shape=[None, 1])
z = tf.keras.layers.Conv1D(32, kernel_size=2, padding="causal")(x)
z = tf.nn.relu(z)  
model = tf.keras.models.Model(inputs=[x], outputs=[z])
model.summary()
model.save('ModelWithTFSymbol')
```

Saving this in TensorFlow 2.3.0 will give you a TensorFlowOpLayer that has its 'call' graph serialized, containing the tf.raw_ops.Relu node that I use to concretely identify this as a ReLU activation operation. 
Model: "functional_1"
```
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, None, 1)]         0         
                                                                 
 conv1d (Conv1D)             (None, None, 32)          96        
                                                                 
 tf_op_layer_Relu (TensorFlo  (None, None, 32)         0         
 wOpLayer)                                                       
                                                                 
=================================================================
```

Saving the same model in TensorFlow 2.6.0+ will give you a TFOpLambda layer for the 'tf.nn.relu' symbol, that does not have its 'call' graph serialized in the object_graph_def. 
Model: "model_9"
```
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_13 (InputLayer)       [(None, None, None, 1)]   0         
                                                                 
 conv1d_13 (Conv1D)          (None, None, None, 32)    96        
                                                                 
 tf.nn.relu_2 (TFOpLambda)   (None, None, None, 32)    0         
                                                                 
=================================================================
```

The most information we have in this case is in the TFOpLambda node's metadata (meta_graphs > object_graph_def > TFOpLambda node >user_object > metadata) as follows:

```
{
	"name": "tf.nn.relu_13",
	"trainable": true,
	"expects_training_arg": false,
	"dtype": "float32",
	"batch_input_shape": null,
	"stateful": false,
	"must_restore_from_config": true,
	"class_name": "TFOpLambda",
	"config": {
		"name": "tf.nn.relu_13",
		"trainable": true,
		"dtype": "float32",
		"function": "nn.relu"
	},
	"inbound_nodes": [
		[
			"conv1d_100",
			0,
			0,
			{
				"name": null
			}
		]
	],
	"shared_object_id": 4
}

```
I have the following questions regarding TFOpLambda layers:

1. Is there a way to always save the 'call' method graph in SavedModels for TFOpLambda layers? Basically a way to keep the older TensorFlowOpLayer behavior in newer versions of TensorFlow?
2. What is the benefit of saving TF Symbols as TFOpLambda layers over the original TensorFlowOpLayers?

