C++ API `SparseApplyAdadelta` segfaults due to lack of shape check
Hi, I'm Paridhi and I'm new to this community. I would like to contribute, I've looked at the issues with labels - "good fist time" and "contribution welcome" but those issues are in stale state. 
Please let me know if I can begin with this issue or any other relatively easier issue present in the queue. Thank you. @Sehun0819,
The related PR which was proposed C++ API SparseApplyAdadelta segfaults due to lack of input shape check has been merged and also the changes are available in the `training_ops.cc` file

https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/ops/training_ops.cc#L63

```python
  const auto rank = c->Rank(grad);
  if (!rank) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Argument grad must not be a scalar. ", "Got grad with rank ", rank));
```

Thank you!
### Issue type

Bug

### Have you reproduced the bug with TensorFlow Nightly?

Yes

### Source

source

### TensorFlow version

tf 2.17

### Custom code

Yes

### OS platform and distribution

Linux Ubuntu 22.04 LTS

### Mobile device

_No response_

### Python version

3.11.7

### Bazel version

6.5.0

### GCC/compiler version

clang 16

### CUDA/cuDNN version

_No response_

### GPU model and memory

_No response_

### Current behavior?

C++ API `SparseApplyAdadelta` segfaults due to lack of input shape check.

[Error location](https://github.com/tensorflow/tensorflow/blob/f647f0cf7c36c7bb7ec531f11df1a028e343749a/tensorflow/core/ops/training_ops.cc#L63):
```C++
  TF_RETURN_IF_ERROR(c->Merge(c->Dim(indices, 0), c->Dim(grad, 0), &unused));
```
At `c->Dim(grad, 0)`, it reads 0th dim without checking rank of `grad`. Therefore when a scalar(0-rank) is given for arg `grad` it crashes.

Note that same things happen for other `SparseApply*` APIs(`SparseApplyAdagrad`, `SparseApplyAdagradDA`, `SparseApplyFtrl`, `SparseApplyFtrlV2`, `SparseApplyMomentum`, `SparseApplyProximalAdagrad`, `SparseApplyProximalGradientDescent`).

### Standalone code to reproduce the issue

```C++
#include "tensorflow/cc/framework/scope.h"
#include "tensorflow/core/graph/graph.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/cc/ops/array_ops.h"
#include "tensorflow/cc/ops/standard_ops.h"

using namespace tensorflow;

int main() {
  SessionOptions options;
  std::unique_ptr<tensorflow::Session>
    session(tensorflow::NewSession(options));

  Scope scope = Scope::NewRootScope();

  Input var = ops::Variable(scope, {1,1,1,1}, DT_FLOAT);
  Input accum = ops::Variable(scope, {1,1,1,1}, DT_FLOAT);
  Input accum_update = ops::Variable(scope, {1,1,1,1}, DT_FLOAT);
  auto target = ops::SparseApplyAdadelta(scope.WithOpName("target"), var, accum, accum_update, 0.1f, 0.1f, 0.1f, 0.1f, {1});

  GraphDef graph_def;
  TF_CHECK_OK(scope.ToGraphDef(&graph_def));

  Status status = session->Create(graph_def);
  if (!status.ok()) {
    LOG(FATAL) << "Could not create session: " << status.message();
  }

  std::vector<Tensor> outputs;
  status = session->Run({}, {"target"}, {""}, &outputs);
  if (!status.ok()) {
    LOG(FATAL) << "Could not run session: " << status.message();
  }

  return 0;
}
```


### Relevant log output

```shell
Segmentation fault (core dumped)
```
