jacobian computation throws ValueError for LinearOperatorFullMatrix: object of type 'LinearOperatorFullMatrix' has no len()
Hi @trickiwoo ,

I can able to replicate the behaviour reported behaviour and attached [gist](https://colab.research.google.com/gist/SuryanarayanaY/a9a8f382b07474b77f0ae111b37b59e2/61060.ipynb) for reference. `tf.linalg.LinearOperatorFullMatrix` has no gradient implementation in TF2.12 but in tf-nightly it seems implemented. 

However `LinearOperatorFullMatrix` has an attribute called `shape` that can return the shape of its object.You can refer the same in gist. 

IMO jacobians seems not implemented yet for `tf.linalg.LinearOperatorFullMatrix` which might be the reason for the error. It might be a feature request. I will escalate the issue to the Dev team and let's hear from them.



Thanks!
 Thanks @SuryanarayanaY for looking into this!
It is very interesting that for `LinearOperatorFullMatrix` objects `x.shape` can return the correct shape, but `tf.shape(x)` will result in an error. IMO this also seems to be an error in the `LinearOperatorFullMatrix` implementation (probably unrelated to the gradient implementation). @trickiwoo @SuryanarayanaY It seems TensorFlow isn't able to handle this operation because `LinearOperatorFullMatrix` isn't a tensor, but a linear operator. So, we must make sure we're operating on tensor values within the context of the `GradientTape` and use `mat` directly, since `LinearOperatorFullMatrix` isn't directly supported as a gradient source or target. Try running
```
import tensorflow as tf

mat = tf.Variable([[1., 2.], [3., 4.]])
mat_reshaped = tf.reshape(mat, [-1])

with tf.GradientTape(persistent=True) as tape:
    tape.watch(mat)
    # Suppose the function we're interested in is simply the sum of the matrix elements
    output = tf.reduce_sum(mat)
    # Compute the gradient
    grad = tape.gradient(output, mat)
    print('Gradient:', grad)

    # To compute the Jacobian, we use a 1-D tensor
    tape.watch(mat_reshaped)
    output_reshaped = tf.reduce_sum(mat_reshaped)
    jac = tape.jacobian(output_reshaped, mat_reshaped)
    print('Jacobian:', jac)
``` Also, computing the gradient outside of the `with tf.GradientTape(persistent=True) as tape:` block as suggested by the console warning `WARNING:tensorflow:Calling GradientTape.gradient on a persistent tape inside its context is significantly less efficient than calling it outside the context (it causes the gradient ops to be recorded on the tape, leading to increased CPU and memory usage). Only call GradientTape.gradient inside the context if you actually want to trace the gradient in order to compute higher order derivatives.` is very straightforward:
```
import tensorflow as tf

mat = tf.Variable([[1., 2.], [3., 4.]])
mat_reshaped = tf.reshape(mat, [-1])

with tf.GradientTape(persistent=True) as tape:
    tape.watch(mat)
    output = tf.reduce_sum(mat)
    tape.watch(mat_reshaped)
    output_reshaped = tf.reduce_sum(mat_reshaped)

# Compute the gradient outside of the context
grad = tape.gradient(output, mat)
print('Gradient:', grad)

# Compute the Jacobian outside of the context
jac = tape.jacobian(output_reshaped, mat_reshaped)
print('Jacobian:', jac)
```

<details><summary>Click to expand!</summary> 
 
 ### Issue Type

Bug

### Have you reproduced the bug with TF nightly?

Yes

### Source

source

### Tensorflow Version

2.14.0-dev20230621

### Custom Code

Yes

### OS Platform and Distribution

Linux Ubuntu 20.04

### Mobile device

_No response_

### Python version

3.9

### Bazel version

_No response_

### GCC/Compiler version

_No response_

### CUDA/cuDNN version

_No response_

### GPU model and memory

_No response_

### Current Behaviour?

When computing jacobian for a `LinearOperatorFullMatrix`, TF throws an error: `ValueError: TypeError: object of type 'LinearOperatorFullMatrix' has no len()`.

I think the problem here might be that `len()` or `shape` is not implemented for `LinearOperatorFullMatrix`. If I just take the shape of a `LinearOperatorFullMatrix`, I can see the same error.

```
import tensorflow as tf
linop = tf.linalg.LinearOperatorFullMatrix(mat)
print(tf.shape(linop)) # Fails
# ValueError: TypeError: object of type 'LinearOperatorFullMatrix' has no len()
```

### Standalone code to reproduce the issue

```shell
import tensorflow as tf

mat = tf.Variable([[1., 2.], [3., 4.]])

with tf.GradientTape(persistent=True) as tape:
    tape.watch(mat)
    output = tf.linalg.LinearOperatorFullMatrix(mat)
    grad = tape.gradient(output, mat) # This works
    print('grad: ', grad)
    jac = tape.jacobian(output, mat) # This fails
    # ValueError: TypeError: object of type 'LinearOperatorFullMatrix' has no len()
```


### Relevant log output

```shell
grad:  tf.Tensor(
[[1. 1.]
 [1. 1.]], shape=(2, 2), dtype=float32)

Traceback
.../tensorflow/python/framework/constant_op.py", line 101, in convert_to_eager_tensor
    return ops.EagerTensor(value, ctx.device_name, dtype)
ValueError: TypeError: object of type 'LinearOperatorFullMatrix' has no len()
```
</details>