diff --git a/render_example/lib/Drupal/render_example/Tests/RenderExampleTest.php b/render_example/lib/Drupal/render_example/Tests/RenderExampleTest.php
new file mode 100644
index 0000000..a5d7c74
--- /dev/null
+++ b/render_example/lib/Drupal/render_example/Tests/RenderExampleTest.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * @file
+ * Contains RenderExampleTest.
+ */
+
+namespace Drupal\render_example\Tests;
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests for the render_example module.
+ */
+class RenderExampleTest extends WebTestBase {
+  public static $modules = array('devel', 'render_example');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Render example functionality',
+      'description' => 'Test Render Example',
+      'group' => 'Examples',
+      // @todo Figure out if this is used, inherited from D7.
+      'dependencies' => array('devel'),
+    );
+  }
+
+  /**
+   * Assert that all of the xpaths in the array have results.
+   *
+   * @param $xpath_array
+   *   An array of xpaths, each of which must return something.
+   */
+  function assertRenderResults($xpath_array) {
+    foreach ($xpath_array as $xpath) {
+      $result = $this->xpath($xpath);
+      $this->assertTrue(!empty($result), format_string('Found xpath %xpath', array('%xpath' => $xpath)));
+    }
+  }
+
+  /**
+   * Asserts that the string value of the result is the same as the passed text.
+   *
+   * @param $xpath_array
+   *   Array of keyed arrays of tests to be made. Each child array consists of
+   *   $xpath => $expected_text
+   */
+  function assertRenderedText($xpath_array) {
+    foreach ($xpath_array as $xpath => $text) {
+      $result = $this->xpath($xpath);
+      $this->assertTrue((string)$result[0][0] == $text, format_string('%ary selects text %text', array('%ary' => $xpath, '%text' => $text)));
+    }
+  }
+
+  /**
+   * Login user, create an example node, and test blog functionality through the admin and user interfaces.
+   */
+  function testRenderExampleBasic() {
+    // Create a user that can access devel information and log in.
+    $web_user = $this->drupalCreateUser(array('access devel information', 'access content'));
+    $this->drupalLogin($web_user);
+
+    // Turn on the block render array display and make sure it shows up.
+    $edit = array(
+      'render_example_show_block' => TRUE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+
+    $xpath_array = array(
+      "//div[@id='sidebar-first']//fieldset[starts-with(@id, 'edit-render-example-block-fieldset')]",
+      '//*[@id="content"]//fieldset[contains(@id,"edit-render-example-block-fieldset")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+
+    // Turn off block render array display and turn on the page render array
+    // display.
+    $edit = array(
+      'render_example_show_page' => TRUE,
+      'render_example_show_block' => FALSE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+
+    $xpath_array = array(
+      '//*[@id="content"]//fieldset[starts-with(@id,"edit-render-example-page-fieldset")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+    // Add note about render arrays to the top of sidebar_first.
+    $edit = array(
+      'render_example_note_about_render_arrays' => TRUE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+    $xpath_array = array(
+      '//*[@id="sidebar-first"]//ol//li[starts-with(.,"Render arrays are everywhere")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+    // Move the navigation menu to the top of the content area.
+    $edit = array(
+      'render_example_move_navigation_menu' => TRUE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+    $xpath_array = array(
+      '//*[@id="content"]//h2[starts-with(.,"Navigation")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+    // Skip a test for reversing order of sidebar_first as I think it would
+    // be too fragile.
+
+    // Test the addition of #prefix and #suffix
+    $edit = array(
+      'render_example_prefix' => TRUE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+    $xpath_array = array(
+      '//*[@id="sidebar-first"]//*[contains(@class, "block-prefix")]/span[contains(@class, "block-suffix")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+    // Test some rendering facets of the various render examples
+    $this->drupalGet('examples/render_example/arrays');
+    $content = $this->xpath('//*[@class="render-array"][1]');
+
+    $xpath_array = array(
+      '//div[@class="rendered"][starts-with(.,"Some basic text in a #markup")]' => 'Some basic text in a #markup (shows basic markup and how it is rendered)',
+      '//div[@class="rendered"][starts-with(.,"This is some text that should be put to")]' => 'This is some text that should be put together | This is some more text that we need | ',
+      '//div[@class="rendered"][starts-with(.,"The current time was")]' => 'The current time was  when this was cached. Updated every  seconds',
+      '//div[@class="rendered"]/div[text()][starts-with(.,"(prefix)This one")]' => '(prefix)This one adds a prefix and suffix, which put a div around the item(suffix)',
+      '//div[@class="rendered"]/div[text()][starts-with(.,"markup for pre_")]' => 'markup for pre_render and post_render example',
+      '//div[@class="rendered"]/div[text()][starts-with(.,"This markup was added")]' => 'This markup was added after rendering by a #post_render',
+      '//div[@class="rendered"]/div[text()][starts-with(.,"This #suffix")]' => 'This #suffix was added by a #pre_render',
+    );
+    $this->assertRenderedText($xpath_array);
+  }
+}
diff --git a/render_example/render_example.css b/render_example/render_example.css
new file mode 100644
index 0000000..0da7f30
--- /dev/null
+++ b/render_example/render_example.css
@@ -0,0 +1,20 @@
+.render-array {
+  border: 2px solid #000;
+  margin-top: 10px;
+  padding-left: 5px;
+  padding-top: 5px;
+}
+
+.render-header {
+  font-size: large;
+  font-style: italic;
+}
+
+.unrendered-label {
+  font-style: italic;
+  margin-top: 10px;
+}
+
+.rendered {
+  background-color: #add8e6;
+}
diff --git a/render_example/render_example.info b/render_example/render_example.info
new file mode 100644
index 0000000..e1b4605
--- /dev/null
+++ b/render_example/render_example.info
@@ -0,0 +1,7 @@
+name = Render example
+description = Demonstrates drupal_render's capabilities and altering render arrays
+package = Example modules
+core = 8.x
+; @todo Remove dependency?
+dependencies[] = devel
+stylesheets[all][] = render_example.css
diff --git a/render_example/render_example.install b/render_example/render_example.install
new file mode 100644
index 0000000..a6bd4cc
--- /dev/null
+++ b/render_example/render_example.install
@@ -0,0 +1,16 @@
+<?php
+/**
+ * @file
+ * Install, update and uninstall functions for the render_example module.
+ */
+
+/**
+ * Implements hook_uninstall().
+ */
+function render_example_uninstall() {
+  variable_del('render_example_show_page');
+  variable_del('render_example_show_block');
+  variable_del('render_example_reverse_sidebar');
+  variable_del('render_example_note_about_render_arrays');
+  variable_del('render_example_move_navigation_menu');
+}
diff --git a/render_example/render_example.module b/render_example/render_example.module
new file mode 100644
index 0000000..ad2a4b9
--- /dev/null
+++ b/render_example/render_example.module
@@ -0,0 +1,555 @@
+<?php
+/**
+ * @file
+ * Demonstrates render arrays.
+ */
+
+/**
+ * @defgroup render_example Example: Render
+ * @ingroup examples
+ * @{
+ * Demonstrate how render arrays are arranged and how they can be altered.
+ * This alters blocks and the page to show the actual render array
+ * that is being used to create each item.
+ *
+ * @see drupal_render()
+ */
+
+// This allows drupal_var_export() to work.
+require_once('core/includes/utility.inc');
+
+/**
+ * Implements hook_menu().
+ */
+function render_example_menu() {
+  $items['examples/render_example'] = array(
+    'title' => 'Render Example',
+    'page callback' => 'render_example_info',
+    'access callback' => TRUE,
+  );
+  $items['examples/render_example/altering'] = array(
+    'title' => 'Alter pages and blocks',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('render_example_demo_form'),
+    'access arguments' => array('access devel information'),
+  );
+  $items['examples/render_example/arrays'] = array(
+    'title' => 'Render array examples',
+    'page callback' => 'render_example_arrays',
+    'access callback' => TRUE,
+  );
+
+  return $items;
+}
+
+
+/**
+ * Simple basic information about the module; an entry point.
+ */
+function render_example_info() {
+  return t('The render example provides a <ul><li><a href="!arrays">demonstration of of render array usage</a></li><li><a href="!alter">using hook_page_alter()</a> to make various changes on a page.</li></ul>', array('!arrays' => url('examples/render_example/arrays'), '!alter' => url('examples/render_example/altering')));
+}
+
+
+/**
+ * Provides a number of render arrays and show what they do.
+ *
+ * Each array is keyed by a description; it's returned for rendering at page
+ * render time. It's easy to add new examples to this.
+ *
+ * The array items in $demos are intended to be raw, normal render arrays
+ * that can be experimented with to end up with different outcomes.
+ */
+function render_example_arrays() {
+
+  $interval = 60; // Interval in seconds for cache update with #cache.
+
+  $demos = array(
+    // Demonstrate the simplest markup, a #markup element.
+    t('Super simple #markup')  => array(
+      '#markup' => t('Some basic text in a #markup (shows basic markup and how it is rendered)'),
+    ),
+
+    // Shows how #prefix and #suffix can add markup into an array.
+    t('Using #prefix and #suffix') => array(
+      '#markup' => t('This one adds a prefix and suffix, which put a div around the item'),
+      '#prefix' => '<div><br/>(prefix)<br/>',
+      '#suffix' => '<br/>(suffix)</div>',
+    ),
+
+    // When #theme is provided, it is the #theme function's job to figure out
+    // the meaning of the render array. The #theme function receives the entire
+    // element in $variables and must return it, where it will be the content
+    // of '#children'. When a #theme or other function is provided, custom
+    // properties can be invented and used as needed, as the #separator
+    // property provided here.
+    //
+    // If #theme is not provided, either explicitly or by the underlying
+    // element, then the children are rendered using their own properties and
+    // the results go into #children.
+    t('theme for an element') => array(
+      'child' => array(
+        t('This is some text that should be put together'),
+        t('This is some more text that we need'),
+      ),
+      '#separator' => ' | ',  // Made up for this theme function.
+      '#theme' => 'render_example_aggregate',
+    ),
+
+    // #theme_wrappers provides an array of theme functions which theme the
+    // envelope or "wrapper" of a set of child elements. The theme function
+    // finds its element children (the sub-arrays) already rendered in
+    // '#children'.
+    t('theme_wrappers demonstration') => array(
+      'child1' => array('#markup' => t('Markup for child1')),
+      'child2' => array('#markup' => t('Markup for child2')),
+      '#theme_wrappers' => array('render_example_add_div', 'render_example_add_notes'),
+    ),
+
+    // Add '#pre_render' and '#post_render' handlers.
+    // - '#pre_render' functions get access to the array before it is rendered
+    //   and can change it. This is similar to a theme function, but it is a
+    //   specific fixed function and changes the array in place rather than
+    //   rendering it..
+    // - '#post_render' functions get access to the rendered content, but also
+    //   have the original array available.
+    t('pre_render and post_render') => array(
+      '#markup' => '<div style="color:green">' . t('markup for pre_render and post_render example') . '</div>',
+      '#pre_render' => array('render_example_add_suffix'),
+      '#post_render' => array('render_example_add_prefix'),
+    ),
+
+    // Cache an element for $interval seconds using #cache.
+    // The assumption here is that this is an expensive item to render, perhaps
+    // large or otherwise expensive. Of course here it's just a piece of markup,
+    // so we don't get the value.
+    //
+    // #cache allows us to set
+    // - 'keys', an array of strings that will create the string cache key.
+    // - 'bin', the cache bin
+    // - 'expire', the expire timestamp. Note that this is actually limited
+    //   to the granularity of a cron run.
+    // - 'granularity', a bitmask determining at what level the caching is done
+    //   (user, role, page).
+    t('cache demonstration') => array(
+      // If your expensive function were to be executed here it would happen
+      // on every page load regardless of the cache. The actual markup is
+      // added via the #pre_render function, so that drupal_render() will only
+      // execute the expensive function if this array has not been cached.
+      '#markup' => '',
+      '#pre_render' => array('render_example_cache_pre_render'),
+      '#cache' => array(
+        'keys' => array('render_example', 'cache', 'demonstration'),
+        'bin' => 'cache',
+        'expire' => time() + $interval,
+        'granularity' => DRUPAL_CACHE_PER_PAGE | DRUPAL_CACHE_PER_ROLE,
+      ),
+    ),
+  );
+
+
+  // The rest of this function just places the above arrays in a context where
+  // they can be rendered (hopefully attractively and usefully) on the page.
+  $page_array = array();
+  foreach ($demos as $key => $item) {
+    $page_array[$key]['#theme_wrappers'] = array('render_array');
+    $page_array[$key]['#description'] = $key;
+
+    $page_array[$key]['unrendered'] = array(
+      '#prefix' => '<div class="unrendered-label">' . t('Unrendered array (as plain text and with a krumo version)') . ':</div>',
+      '#type' => 'markup',
+      '#markup' => htmlentities(drupal_var_export($item)),
+    );
+    $page_array[$key]['kpr'] = array(
+      // The kpr() function is from devel module and is here only allow us
+      // to output the array in a way that's easy to explore.
+      '#markup' => kpr($item, TRUE),
+    );
+    $page_array[$key]['hr'] = array('#markup' => '<hr/>');
+    $page_array[$key]['rendered'] = array($item);
+    $page_array[$key]['rendered']['#prefix'] = '<p><em>Rendered version (light blue)</em>:</p>' . '<div class="rendered">';
+    $page_array[$key]['rendered']['#suffix'] = '</div>';
+  }
+
+  return $page_array;
+}
+
+/**
+ * A '#pre_render' function.
+ *
+ * @param $element
+ *   The element which will be rendered.
+ *
+ * @return
+ *   The altered element. In this case we add the #markup.
+ */
+function render_example_cache_pre_render($element) {
+  $element['#markup'] = render_example_cache_expensive();
+
+  // The following line is due to the bug described in
+  // http://drupal.org/node/914792. A #markup element's #pre_render must set
+  // #children because it replaces the default #markup pre_render, which is
+  // drupal_pre_render_markup().
+  $element['#children'] = $element['#markup'];
+  return $element;
+}
+
+/**
+ * A potentially expensive function.
+ *
+ * @return
+ *   Some demo text.
+ */
+function render_example_cache_expensive() {
+  $interval = 60;
+  $time_message = t('The current time was %time when this was cached. Updated every %interval seconds', array('%time' => date('r'), '%interval' => $interval));
+  // Uncomment the following line to demonstrate that this function is not
+  // being run when the rendered array is cached.
+  // drupal_set_message($time_message);
+  return $time_message;
+}
+
+/**
+ * A '#pre_render' function.
+ *
+ * @param $element
+ *   The element which will be rendered.
+ *
+ * @return
+ *   The altered element. In this case we add a #prefix to it.
+ */
+function render_example_add_suffix($element) {
+  $element['#suffix'] = '<div style="color:red">' . t('This #suffix was added by a #pre_render') . '</div>';
+
+  // The following line is due to the bug described in
+  // http://drupal.org/node/914792. A #markup element's #pre_render must set
+  // #children because it replaces the default #markup pre_render, which is
+  // drupal_pre_render_markup().
+  $element['#children'] = $element['#markup'];
+  return $element;
+}
+
+/**
+ * A '#post_render' function to add a little markup onto the end markup.
+ *
+ * @param $markup
+ *   The rendered element.
+ * @param $element
+ *   The element which was rendered (for reference)
+ *
+ * @return
+ *   Markup altered as necessary. In this case we add a little postscript to it.
+ */
+function render_example_add_prefix($markup, $element) {
+  $markup = '<div style="color:blue">This markup was added after rendering by a #post_render</div>' . $markup;
+  return $markup;
+}
+
+/**
+ * A #theme function.
+ *
+ * This #theme function has the responsibility of consolidating/rendering the
+ * children's markup and returning it, where it will be placed in the
+ * element's #children property.
+ */
+function theme_render_example_aggregate($variables) {
+  $output = '';
+  foreach (element_children($variables['element']['child']) as $item) {
+    $output .= $variables['element']['child'][$item] . $variables['element']['#separator'];
+  }
+  return $output;
+}
+
+/*************** Altering Section **************************
+ * The following section of the example builds and arranges the altering
+ * example.
+ */
+
+/**
+ * Builds the form that offers options of what items to show.
+ */
+function render_example_demo_form($form, &$form_state) {
+  $form['description'] = array(
+    '#type' => 'markup',
+    '#markup' => t('This example shows what render arrays look like in the building of a page. It will not work unless the user running it has the "access devel information" privilege. It shows both the actual arrays used to build a page or block and also the capabilities of altering the page late in its lifecycle.'),
+  );
+
+  $form['show_arrays'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Show render arrays'),
+  );
+
+  foreach (array('block', 'page') as $type) {
+    $form['show_arrays']['render_example_show_' . $type] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Show @type render arrays', array('@type' => $type)),
+      '#default_value' => variable_get('render_example_show_' . $type, FALSE),
+    );
+  }
+
+  $form['page_fiddling'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Make changes on page via hook_page_alter()'),
+  );
+  $form['page_fiddling']['render_example_note_about_render_arrays'] = array(
+    '#title' => t('Add a note about render arrays to top of sidebar_first (if it exists)'),
+    '#description' => t('Creates a simple render array that displays the use of #pre_render, #post_render, #theme, and #theme_wrappers.'),
+    '#type' => 'checkbox',
+    '#default_value' => variable_get('render_example_note_about_render_arrays', FALSE),
+  );
+  $form['page_fiddling']['render_example_move_navigation_menu'] = array(
+    '#title' => t('Move the navigation menu to the top of the content area'),
+    '#description' => t('Uses hook_page_alter() to move the navigation menu into another region.'),
+    '#type' => 'checkbox',
+    '#default_value' => variable_get('render_example_move_navigation_menu', FALSE),
+  );
+  $form['page_fiddling']['render_example_reverse_sidebar'] = array(
+    '#title' => t('Reverse ordering of sidebar_first elements (if it exists) - will affect the above'),
+    '#description' => t('Uses hook_page_alter() to reverse the ordering of items in sidebar_first'),
+    '#type' => 'checkbox',
+    '#default_value' => variable_get('render_example_reverse_sidebar', FALSE),
+  );
+  $form['page_fiddling']['render_example_prefix'] = array(
+    '#title' => t('Use #prefix and #suffix to wrap a div around every block'),
+    '#description' => t('Uses hook_page_alter to wrap all blocks with a div using #prefix and #suffix'),
+    '#type' => 'checkbox',
+    '#default_value' => variable_get('render_example_prefix'),
+  );
+
+  return system_settings_form($form);
+}
+
+/**
+ * Implements hook_page_alter().
+ *
+ * Alters the page in several different ways based on how the form has been
+ * configured.
+ */
+function render_example_page_alter(&$page) {
+
+  $original_page = $page;
+
+  // Re-sort the sidebar in reverse order.
+  if (variable_get('render_example_reverse_sidebar', FALSE) && !empty($page['sidebar_first'])) {
+    $page['sidebar_first'] = array_reverse($page['sidebar_first']);
+    foreach (element_children($page['sidebar_first']) as $element) {
+      // Reverse the weights if they exist.
+      if (!empty($page['sidebar_first'][$element]['#weight'])) {
+        $page['sidebar_first'][$element]['#weight'] *= -1;
+      }
+    }
+    $page['sidebar_first']['#sorted'] = FALSE;
+  }
+
+  // Add a list of items to the top of sidebar_first.
+  // This shows how #theme and #theme_wrappers work.
+  if (variable_get('render_example_note_about_render_arrays', FALSE) && !empty($page['sidebar_first'])) {
+    $items = array(
+      t('Render arrays are everywhere in D7'),
+      t('Leave content unrendered as much as possible'),
+      t('This allows rearrangement and alteration very late in page cycle'),
+    );
+
+    $note = array(
+      '#title' => t('Render Array Example'),
+      '#items' => $items,
+
+      // The functions in #pre_render get to alter the actual data before it
+      // gets rendered by the various theme functions.
+      '#pre_render' => array('render_example_change_to_ol'),
+      // The functions in #post_render get both the element and the rendered
+      // data and can add to the rendered data.
+      '#post_render' => array('render_example_add_hr'),
+      // The #theme theme operation gets the first chance at rendering the
+      // element and its children.
+      '#theme' => 'item_list',
+      // Then the theme operations in #theme_wrappers can wrap more around
+      // what #theme left in #chilren.
+      '#theme_wrappers' => array('render_example_add_div', 'render_example_add_notes'),
+      '#weight' => -9999,
+    );
+    $page['sidebar_first']['render_array_note'] = $note;
+    $page['sidebar_first']['#sorted'] = FALSE;
+  }
+
+
+  // Move the navigation menu into the content area.
+  if (variable_get('render_example_move_navigation_menu', FALSE) && !empty($page['sidebar_first']['system_navigation']) && !empty($page['content'])) {
+    $page['content']['system_navigation'] = $page['sidebar_first']['system_navigation'];
+    $page['content']['system_navigation']['#weight'] = -99999;
+    unset($page['content']['#sorted']);
+    unset($page['sidebar_first']['system_navigation']);
+  }
+
+  // Show the render array used to build the page render array display.
+  if (variable_get('render_example_show_page', FALSE)) {
+    $form['render_example_page_fieldset'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Page render array'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    );
+    $form['render_example_page_fieldset']['markup'] = array(
+      // The kpr() function is from devel module and is here only allow us
+      // to output the array in a way that's easy to explore.
+      '#markup' => kpr($page, TRUE),
+    );
+    $page['content']['page_render_array'] = drupal_get_form('render_example_embedded_form', $form);
+    $page['content']['page_render_array']['#weight'] = -999999;
+    $page['content']['#sorted'] = FALSE;
+  }
+
+  // Add render array to the bottom of each block
+  if (variable_get('render_example_show_block', FALSE)) {
+    foreach (element_children($page) as $region_name) {
+      foreach (element_children($page[$region_name]) as $block_name) {
+
+        // Push the block down a level so we can add another block after it.
+        $old_block = $page[$region_name][$block_name];
+        $page[$region_name][$block_name] = array(
+          $block_name => $old_block,
+        );
+        $form['render_example_block_fieldset'] = array(
+          '#type' => 'fieldset',
+          '#title' => t('Block render array'),
+          '#collapsible' => TRUE,
+          '#collapsed' => TRUE,
+        );
+
+        $form['render_example_block_fieldset']['markup'] = array(
+          '#type' => 'item',
+          '#title' => t('%blockname block render array', array('%blockname' => $block_name)),
+          // The kpr() function is from devel module and is here only allow us
+          // to output the array in a way that's easy to explore.
+          '#markup' => kpr($old_block, TRUE),
+        );
+
+        // Add the new block that contains the render array.
+        $page[$region_name][$block_name]['render_example_block_render_array'] =  drupal_get_form('render_example_embedded_form', $form);
+        $page[$region_name][$block_name]['render_example_block_render_array']['#weight'] = 999;
+      }
+    }
+  }
+
+  // Add #prefix and #suffix to a block to wrap a div around it.
+  if (variable_get('render_example_prefix', FALSE)) {
+    foreach (element_children($page) as $region_name) {
+      foreach (element_children($page[$region_name]) as $block_name) {
+        $block = &$page[$region_name][$block_name];
+        $block['#prefix'] = '<div class="block-prefix"><p>Prefixed</p>';
+        $block['#suffix'] = '<span class="block-suffix">Block suffix</span></div>';
+      }
+    }
+  }
+  $altered_page = $page;
+
+}
+
+/**
+ * Utility function to build a named form given a set of form elements.
+ *
+ * This is a standard form builder function that takes an additional array,
+ * which is itself a form.
+ *
+ * @param $form
+ *   The standard $form
+ * @param $form_state
+ *   The standard $form_state
+ * @param $form_items
+ *   The form items to be included in this form.
+ */
+function render_example_embedded_form($form, &$form_state, $form_items) {
+  return $form_items;
+}
+
+/**
+ * Implements hook_theme().
+ */
+function render_example_theme() {
+  $items = array(
+    'render_example_add_div' => array(
+      'render element' => 'element',
+    ),
+    'render_example_add_notes' => array(
+      'render element' => 'element',
+    ),
+    'render_array' => array(
+      'render element' => 'element',
+    ),
+    'render_example_aggregate' => array(
+      'render element' => 'element',
+    ),
+  );
+  return $items;
+}
+
+/**
+ * Wraps a div around the already-rendered #children.
+ */
+function theme_render_example_add_div($variables) {
+  $element = $variables['element'];
+  $output = '<div class="render-example-wrapper-div">';
+  $output .= $element['#children'];
+  $output .= '</div>';
+  return $output;
+}
+
+/**
+ * Wraps a div and add a little text after the rendered #children.
+ */
+function theme_render_example_add_notes($variables) {
+  $element = $variables['element'];
+  $output = '<div class="render-example-notes-wrapper-div">';
+  $output .= $element['#children'];
+  $output .= '<em>' . t('This is a note added by a #theme_wrapper') . '</em>';
+  $output .= '</div>';
+
+  return $output;
+}
+
+/**
+ * Themes the render array (from the demonstration page).
+ */
+function theme_render_array($variables) {
+  $heading = '<div class="render-header">' . $variables['element']['#description'] . '</div>';
+
+  $rendered = '<div class="render-array">' . $heading . $variables['element']['#children'] . '</div>';
+  return $rendered;
+}
+
+/**
+ * Adds a #type to the element before it gets rendered.
+ * In this case, changes from the default 'ul' to 'ol'.
+ *
+ * @param $element
+ *   The element to be altered, in this case a list, ready for theme_item_list.
+ *
+ * @return
+ *   The altered list (with '#type')
+ */
+function render_example_change_to_ol($element) {
+  $element['#type'] = 'ol';
+  return $element;
+}
+
+/**
+ * This #post_render function gets to alter the rendered output after all
+ * theme functions have acted on it, and it receives the original data, so
+ * can make decisions based on that. In this example, no use is made of the
+ * passed-in $element.
+ *
+ * @param $markup
+ *   The already-rendered data
+ * @param unknown_type $element
+ *   The data element that was rendered
+ *
+ * @return
+ *   The altered data.
+ */
+function render_example_add_hr($markup, $element) {
+  $output = $markup . '<hr />';
+  return $output;
+}
+/**
+ * @} End of "defgroup render_example".
+ */
