[WebGPU] Add GRU operator support (#29840)
### Description
Adds the `GRU` operator to the WebGPU execution provider, following the
existing WebGPU `LSTM` kernel. Registered for opsets 7-13 and 14+, with
float (`T`) and int32 (`T1`) type constraints.
Each timestep is computed in two passes because, for
`linear_before_reset = 0`, the recurrent term `(r (.) H_prev) * Rh^T`
mixes reset-gate values across hidden units and so cannot be produced by
a single per-unit thread:
- `GruGateProgram` computes the update (`z`) and reset (`r`) gates for
the whole `[batch, hidden]` tensor. For `linear_before_reset = 0` it
emits `r (.) H_prev` directly; for `linear_before_reset = 1` it emits
`r` so the reset is applied after the recurrent matmul.
- `GruHiddenProgram` computes the hidden gate and the new state `Ht = (1
- z) (.) h + z (.) H_prev`.
Supported: bias, forward / reverse / bidirectional directions,
`sequence_lens` masking, the `layout` attribute, `clip`, and both
`linear_before_reset` modes. Activations are limited to
Sigmoid/Tanh/Relu (as in the WebGPU LSTM kernel).
### Motivation and Context
Resolves #29452. GRU was the natural follow-up to the recently added
WebGPU LSTM support, letting models with GRU nodes run on the WebGPU EP.
### Testing
Coverage comes from the existing GRU operator tests in
`deep_cpu_gru_op_test.cc`, which now also execute against the WebGPU EP
(`base_tester` iterates the WebGPU EP when built with `--use_webgpu`).
Cases using activations the kernel does not implement (e.g.
`LeakyRelu`/`ScaledTanh`) are excluded from the WebGPU run via the
shared test helper.
The gate math and buffer indexing were cross-checked against an
independent ONNX-spec GRU reference for both `linear_before_reset`
modes, with and without bias (match to ~1e-16). Validation on real
WebGPU hardware is left to CI.
---------
Co-authored-by: Isabel Wu <231155141+wuisabel-gif@users.noreply.github.com>